package zhengyisky.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.thoughtworks.xstream.XStream;
import entity.WechatRequestEntity;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import util.QRCodeUtil;
import zhengyisky.service.TestService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.*;

@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.mchid}")
    private String mchid;

    @Value("${wechat.apikey}")
    private String apikey;


    /**
     * 调用统一下单接口获取Code_Url并转化为二维码返回给前端
     * @param orderid 订单编号
     * @param money 订单金额
     * @param response 响应对象
     */

    @RequestMapping("/wechatImg")
    public void wechatImg(String orderid, Integer money, HttpServletRequest request, HttpServletResponse response){
        System.out.println(orderid+"===="+money);

        //封装请求XML
        Map<String,Object> reqMap = new HashMap<String,Object>();
        reqMap.put("appid",appid);
        reqMap.put("mch_id",mchid);
        reqMap.put("nonce_str",this.randomIntegerCode(32,false));
        reqMap.put("body","微信支付测试订单"+orderid);
        reqMap.put("out_trade_no",orderid);
        reqMap.put("total_fee",money);
        reqMap.put("spbill_create_ip",request.getRemoteAddr());
        reqMap.put("notify_url","http://localhost:8701/wechatReturn");
        reqMap.put("trade_type","NATIVE");
        reqMap.put("sign",this.createSign(reqMap,apikey));

        //把map转化为对象
        ObjectMapper mapper = new ObjectMapper();

        WechatRequestEntity requestEntity = null;
        try {
            String json = mapper.writeValueAsString(reqMap);
            requestEntity = mapper.readValue(json,WechatRequestEntity.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //借助xstream将map转为xml字符串
        XStream xStream = new XStream();
        xStream.alias("xml",WechatRequestEntity.class);
        String reqXml = xStream.toXML(requestEntity);
        reqXml = reqXml.replaceAll("__","_");

        System.out.println(reqXml);

        //发送请求
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        HttpEntity entity = new StringEntity(reqXml,"UTF-8");
        httpPost.setEntity(entity);
        //接收返回的XML
        String result = null;
        try {
            HttpResponse resp = httpClient.execute(httpPost);
            result = EntityUtils.toString(resp.getEntity(),"UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //从返回的XML中取出CODE_URL
        System.out.println(result);



        InputStream in = new ByteArrayInputStream(result.getBytes());

        Map respMap = new HashMap();
        SAXReader reader = new SAXReader();
        try {
            Document doc = reader.read(in);
            Element root = doc.getRootElement();
            List<Element> elements = root.elements();
            for (Element e: elements) {
                respMap.put(e.getName(),e.getStringValue());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        //验签（此接口没必要，由我们提供出来让对方调用的接口在接收到数据时必须验签）
        //生成一个新的签名，需要排除对方传递给我们的sign
        String sign = (String)respMap.get("sign");
        respMap.remove("sign");
        String ourSign = this.createSign(respMap,apikey);
        System.out.println(ourSign);
        System.out.println(sign);
        if(sign.equals(ourSign)){
            System.out.println("此请求来源于微信，对方签名时使用的密钥和我们相同");
        }else{
            System.out.println("请求非法");
        }

        String code_url = (String) respMap.get("code_url");
        //将CODE_URL转化为二维码图片相应给页面
        QRCodeUtil.createQRCode(response, code_url);
    }

    /**
     * 调用订单查询接口获取订单支付状态
     * @return
     */
    @RequestMapping("/getPayStatus")
    public Boolean getPayStatus(String orderid){
        //封装请求XML
        Map<String,Object> reqMap = new HashMap<String,Object>();
        reqMap.put("appid",appid);
        reqMap.put("mch_id",mchid);
        reqMap.put("nonce_str",this.randomIntegerCode(32,false));
        reqMap.put("out_trade_no",orderid);
        reqMap.put("sign",this  .createSign(reqMap,apikey));

        //把map转化为对象
        ObjectMapper mapper = new ObjectMapper();

        WechatRequestEntity requestEntity = null;
        try {
            String json = mapper.writeValueAsString(reqMap);
            requestEntity = mapper.readValue(json,WechatRequestEntity.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //借助xstream将map转为xml字符串
        XStream xStream = new XStream();
        xStream.alias("xml",WechatRequestEntity.class);
        String reqXml = xStream.toXML(requestEntity);
        reqXml = reqXml.replaceAll("__","_");

        System.out.println(reqXml);

        //发送请求
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        HttpEntity entity = new StringEntity(reqXml,"UTF-8");
        httpPost.setEntity(entity);
        //接收返回的XML
        String result = null;
        try {
            HttpResponse resp = httpClient.execute(httpPost);
            result = EntityUtils.toString(resp.getEntity(),"UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //从返回的XML中取出支付结果
        System.out.println(result);

        InputStream in = new ByteArrayInputStream(result.getBytes());
        Map respMap = new HashMap();
        SAXReader reader = new SAXReader();
        try {
            Document doc = reader.read(in);
            Element root = doc.getRootElement();
            List<Element> elements = root.elements();
            for (Element e: elements) {
                respMap.put(e.getName(),e.getStringValue());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        String return_code = (String) respMap.get("return_code");
        String return_msg = (String) respMap.get("return_msg");
        String trade_state = (String) respMap.get("trade_state");
        if(return_msg.equals("OK") && return_code.equals("SUCCESS") && trade_state.equals("SUCCESS")){
            return true;
        }
        return false;
    }

    /**
     * 接收微信支付结果
     * @param message
     */
    @RequestMapping("/wechatReturn")
    public void wechatReturn(String message){
        //验证签名

        //解析XML，拿到订单号和实际付款金额

        //根据订单编号查询订单订单信息

        //判断实际付款金额和查询到的订单信息是否相同

        //修改订单状态，并返回"SUCCESS"

        //调用退款接口，关闭订单，恢复库存。

    }

    /**
     * 生成签名
     * @param source 数据源，需要传输给接口的所有数据（不包含签名字段和空字段）
     * @param key 支付商户的密钥
     * @return 签名
     */
    private String createSign(Map<String,Object> source, String key){
        Set<String> keySet = source.keySet();
        List<String> keyList = new ArrayList(keySet);
        Collections.sort(keyList);
        String url = "";
        for(int i=0; i<keyList.size(); i++){
            url += keyList.get(i)+"="+source.get(keyList.get(i))+"&";
        }
        url += "key=" + key;

        String sign  = DigestUtils.md5Hex(url);
        System.out.println(sign);
        return sign.toUpperCase();
    }

    /**
     * 生成指定长度随机字符串
     * @param length 长度
     * @param type 类型   true:纯数字    false:英文+数字
     * @return
     */
    private String randomIntegerCode(Integer length, Boolean type){
        if(length<1){
            length = 32;
        }
        String result = "";
        Random random = new Random();
        if(type){
            for(int i = 0; i < length; i++){
                result += random.nextInt(10);
            }
        }else{
            String chars = "abcdefghijklmnopqrstuvwxyz1234567890";
            String[] charArray = chars.split("");
            for (int i=0; i<length; i++){
                int index = random.nextInt(chars.length());
                result += charArray[index];
            }
        }
        return result;
    }
}
